/**
 * 4*1000的字符矩阵，仅包含`red`三个字符，要求相邻字符不相等。
 * 问最少要改几个字符
 * 
 * 令Dij是到第i列以状态j结尾的最少修改次数
 * 其中状态j用三进制数表示，`red`分别对应`012`
 * 很容易确定转移方程
 * Dij = 把原始输入改为状态j需要的次数 + min(D[i-1][k], k是所有能与j相邻的状态)
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>

using llt = long long;
using vi = vector<int>;
using pii = pair<int, int>;

const vi Pow {1, 3, 9, 27, 81};
const string T {"red"};

int N, M;
vector<string> A;
vector<vi> D;
vector<vi> Neighbour;

bool isOK(const string & s){
    for(int i=1;i<N;++i){
        if(s[i - 1] == s[i]) return false;
    }
    return true;
}

bool isOK(const vi & s){
    for(int i=1;i<N;++i){
        if(s[i - 1] == s[i]) return false;
    }
    return true;    
}

int f(const string & s, int pos){
    int ans = 0;
    for(int i=0;i<N;++i){
        if(s[i] != A[i + 1][pos]){
            ans += 1;
        }
    }
    return ans;
}

void dfs(int depth, const vi & level, vi & result, vi & ans){
    if(depth == N){
        if(isOK(result)){
            int tmp = 0;
            for(auto it=result.rbegin(),et=result.rend();it!=et;++it){
                tmp = tmp * 3 + *it;
            }
            ans.emplace_back(tmp);
        }
        return;
    }

    for(int i=0;i<3;++i){
        if(i == level[depth]) continue;

        result.push_back(i);
        dfs(depth + 1, level, result, ans);
        result.pop_back();
    }

    return;
}

int proc(){
    int m = Pow[N];
    Neighbour.assign(m, {});
    for(int i=0;i<m;++i){
        vi vec;
        int st = i;
        for(int j=0;j<N;++j){
            vec.emplace_back(st % 3);
            st /= 3;
        }

        if(not isOK(vec)) continue;

        vi tmpvec;
        dfs(0, vec, tmpvec, Neighbour[i]);
    }

    D.assign(M + 1, vi(m, -1));
    fill(D[0].begin(), D[0].end(), 0);

    for(int i=1;i<=M;++i){
        for(int status=0;status<m;++status){
            string s;
            int tmp = status;
            for(int j=0;j<N;++j){
                auto left = tmp % 3;
                s += T[left];
                tmp /= 3;
            }
            if(not isOK(s)) continue;

            int & d = D[i][status];
            D[i][status] = f(s, i);

            tmp = 1E5;
            const vi & neigh = Neighbour[status];
            for(auto j : neigh){
                if(D[i - 1][j] != -1){
                    tmp = min(tmp, D[i - 1][j]);
                }
            }
            d += tmp;
        }
    }

    int ans = 1E5;
    const vi & ret = D[M];
    for(auto i : ret){
        if(i != -1){
            ans = min(ans, i);
        }
    }
    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1; 
    // cin >> nofkase;
    while(nofkase--){
        cin >> N >> M;
        A.assign(N + 1, "");
        for(int i=1;i<=N;++i) {
            cin >> A[i];
            A[i] = " " + A[i];
        }
        cout << proc() << "\n";
    }
    return 0;
}